﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Phone.Shell;

using OpenXLive;
using OpenXLive.Features;

using Tranquillity;
using TranquillityDemos;
using ChaseCameraSample;
using cocos2d;
using CocosDenshion;
using Microsoft.Advertising.Mobile.Xna;

namespace Meteorite
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>


    public class Meteorite : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public static Meteorite game;
        public static AdvertisementManager AdMgr = new AdvertisementManager();
        public static XLiveFormManager livemanager;
        public static RollingNewsBoard NewsBoard;
        public static Texture2D liveBkg;
        
        public static Random random = new Random();

        public static ParticleManager particleManager;
        public static CCApplication application;
        public static ChaseCamera camera;
        public static Ship ship;
        public static StoneManage stoneManager = new StoneManage();

        public static ExplosionEmitter explosionEmitter;
        ExplosionParticleSystem explosionParticleSystem;

        Model stone;
        Sky sky;

        static public bool Pause
        {
            get;
            set;
        }

        int TickCount;
        public Meteorite()
        {
            game = this;

            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);

            // Extend battery life under lock.
            InactiveSleepTime = TimeSpan.FromSeconds(1);

            //graphic
            graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft;
            graphics.PreferredBackBufferWidth = GameConstant.WindowWidth;
            graphics.PreferredBackBufferHeight = GameConstant.WindowHeight;
            graphics.IsFullScreen = true;

            //PhoneAppService
            PhoneApplicationService.Current.Activated += GameActivated;
            PhoneApplicationService.Current.Deactivated += GameDeactivated;


            //Set up cocos2d engine
            application = new AppDelegate(this, graphics);
            this.Components.Add(application);
            

            //Set up particle system
            particleManager = new ParticleManager(this);
            Components.Add(particleManager);

            // Set up the camera
            camera = new ChaseCamera();
            camera.DesiredPositionOffset = new Vector3(0.0f, 0.0f, GameConstant.CameraNormalDistance);
            camera.LookAtOffset = new Vector3(0.0f, 0.0f, 0.0f);
            camera.NearPlaneDistance = 10.0f;
            camera.FarPlaneDistance = 100000.0f;
            
            
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            //XLive
            GameSession session = XLiveGameManager.CreateSession("rajpQASv6Y5uTkMyDx3J8hHC");  
            livemanager = new XLiveFormManager(this, session);
            //manager.NewGameEvent += new EventHandler(manager_NewGameEvent);
            //manager.ResumeGameEvent += new EventHandler(manager_ResumeGameEvent);
            //livemanager.UIExitingEvent += new EventHandler(manager_ExitEvent);
            Components.Add(livemanager);
            //session.CreateSessionCompleted += new AsyncEventHandler(session_CreateCompletedEvent);
            session.Open();

            liveBkg = Content.Load<Texture2D>(GameConstant.Texture_XLive_Bkg);

            //Advertisement
            AdMgr.Initialize
            (
                this,
                GameConstant.Ad_AppID,
                GameConstant.Ad_UnitID,
                GameConstant.Ad_Pos_x,
                GameConstant.Ad_Pos_y,
                GameConstant.Ad_Widht,
                GameConstant.Ad_Height
            );
            AdMgr.SetVisible(false);

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            // TODO: use this.Content to load your game content here
            
            //Dome
            sky = Content.Load<Sky>(GameConstant.Texture_SkyBox);

            //initialize the ship
            ship = new Ship(Content.Load<Model>(GameConstant.Model_Ship), this);
            ship.Position = new Vector3(0, 0, 0);
            //ship.Valid = true;

            camera.ChasePosition = ship.Position;
            camera.ChaseDirection = Vector3.Forward;
            camera.Up = Vector3.Up;

            stone = Content.Load<Model>(GameConstant.Model_Stone_2);
           
            //e.Position = new Vector3(1,0,-6000);         

            Texture2D explosion = Content.Load<Texture2D>(GameConstant.Texture_Explosion);
            explosionParticleSystem = new ExplosionParticleSystem(100, explosion);
            explosionEmitter = new ExplosionEmitter(20);
            explosionParticleSystem.AddEmitter(explosionEmitter);

            particleManager.AddParticleSystem(explosionParticleSystem, BlendState.Additive);

            stoneManager.LoadContent(this);

            NewsBoard = new RollingNewsBoard(livemanager);

            //User data
            UserData.Instance().Load();

            //sound
            SimpleAudioEngine.sharedEngine().preloadBackgroundMusic(CCFileUtils.fullPathFromRelativePath(GameConstant.Sound_Menu_Bkg));
            SimpleAudioEngine.sharedEngine().preloadEffect(CCFileUtils.fullPathFromRelativePath(GameConstant.Sound_Btn));
            SimpleAudioEngine.sharedEngine().setEffectsVolume(0.3f);
            SimpleAudioEngine.sharedEngine().setBackgroundMusicVolume(0.3f);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit

            
#if DEBUG

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                //this.Exit();
            }
#endif
            

            //hardware key
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                if (CCDirector.sharedDirector().runningScene is MainMenuScene)
                {
                    if (null == livemanager.ActiveForm)
                    {
                        UserData.Instance().Save();
                        this.Exit();
                    }
                }
                else if (CCDirector.sharedDirector().runningScene is GameScene)
                {
                    GameScene scene = (GameScene)CCDirector.sharedDirector().runningScene;
                    if (Meteorite.Pause)
                    {
                        scene.Resume();
                    }
                    else
                    {
                        scene.Pause();
                    }
                }
                else if (CCDirector.sharedDirector().runningScene is GameOverScene)
                {
                    CCScene pScene = new MainMenuScene();
                    CCDirector.sharedDirector().replaceScene(pScene);
                }
                else if (CCDirector.sharedDirector().runningScene is StatsticsScene)
                {
                    CCDirector.sharedDirector().popScene();
                }
            }

            if (!Pause)
            {
                TickCount++;
                // TODO: Add your update logic here
                //ship.ProcessInput();
                //之所以把控制飞机放在这是因为这个update跟cocos2d的update不同步，很蛋疼
                if (CCDirector.sharedDirector().runningScene is GameScene)
                {
                    GameScene scene = (GameScene)CCDirector.sharedDirector().runningScene;
                    if (null != scene.Controler )
                    {
                    
                        CCPoint percent = scene.Controler.GetOffsetPercent();
                        Vector3 Force = Vector3.Zero;
                        Force.X = percent.x * GameConstant.ThrustForce;
                        Force.Y = percent.y * GameConstant.ThrustForce;

                        ship.Force = Force;
                    }

                }

                ship.Update(gameTime);

                //UpdateCameraChaseTarget();
                camera.Update(gameTime);

                stoneManager.Update(gameTime);
                //Update manually
                
                particleManager.Update(gameTime);
            }


            //the order : XLiveManager updates first then application 
            livemanager.Update(gameTime);
            application.Update(gameTime);
            //base.Update(gameTime);
            //Debug.WriteLine("2");
            AdGameComponent.Current.Update(gameTime);
        }
        private void UpdateCameraChaseTarget()
        {
            camera.ChasePosition = ship.Position;
            camera.ChaseDirection = Vector3.Forward;
            camera.Up = Vector3.Up;
        }
       
        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            //GraphicsDevice.Clear(Color.CornflowerBlue);
            // TODO: Add your drawing code here

            
            Matrix View = camera.View;
            Matrix Projection = camera.Projection;

            sky.Draw(View, Projection);
            stoneManager.Draw(View, Projection);
            ship.Draw(View, Projection);
            //just ok
            particleManager.SetMatrices(camera.View, camera.Projection);
            particleManager.Draw(gameTime);

            //this trunk must exist,otherwise particleManager will work incorrectly.
            spriteBatch.Begin();
            //spriteBatch.Draw(tex, new Vector2(0, 0), Color.White);
            spriteBatch.End(); 

            //last Draw UI
            application.Draw(gameTime);
            livemanager.Draw(gameTime);
            
            
            spriteBatch.Begin();
            NewsBoard.Draw(this.GraphicsDevice, spriteBatch, gameTime);
            spriteBatch.End();

            AdGameComponent.Current.Draw(gameTime);
            //forbid base.Draw
            //base.Draw(gameTime); 
            

        }

        private void GameActivated(object sender, ActivatedEventArgs e)
        {
            CCDirector.sharedDirector().resume();
            if (0 == UserData.Instance().GetValue(GameConstant.UserData_Sound))
            {
                SimpleAudioEngine.sharedEngine().resumeBackgroundMusic();
            }
        }

        private void GameDeactivated(object sender, DeactivatedEventArgs e)
        {
            CCDirector.sharedDirector().pause();

            SimpleAudioEngine.sharedEngine().pauseBackgroundMusic();
            if (CCDirector.sharedDirector().runningScene is GameScene)
            {
                GameScene scene = (GameScene)CCDirector.sharedDirector().runningScene;
                scene.Pause();
            }
        } 
    }

}
